www.gusucode.com > VC++ 三维图形生成和察看工具 > VC++ 三维图形生成和察看工具/code/mesh/MeshView.cpp
//Download by http://www.NewXing.com // MeshView.cpp : implementation of the CMeshView class // #include "stdafx.h" #include "Mesh.h" #include "MeshDoc.h" #include "MeshView.h" #include "Lib3d/PsRender.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMeshView IMPLEMENT_DYNCREATE(CMeshView, CView) BEGIN_MESSAGE_MAP(CMeshView, CView) //{{AFX_MSG_MAP(CMeshView) ON_WM_PAINT() ON_WM_DESTROY() ON_WM_SIZE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_ERASEBKGND() ON_WM_CREATE() ON_COMMAND(ID_EDIT_COPY, OnEditCopy) ON_COMMAND(ID_EXPORT_EPS, OnExportEps) ON_UPDATE_COMMAND_UI(ID_EXPORT_EPS, OnUpdateExportEps) ON_COMMAND(ID_OPENGL_CLEARCOLOR, OnOpenglClearcolor) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMeshView construction/destruction CMeshView::CMeshView() { // OpenGL m_hGLContext = NULL; m_GLPixelIndex = 0; // Mouse m_LeftButtonDown = FALSE; m_RightButtonDown = FALSE; // Colors m_ClearColorRed = 0.0f; m_ClearColorGreen = 0.0f; m_ClearColorBlue = 0.0f; // Animation m_StepRotationX = 0.0f; m_StepRotationY = 5.0f; m_StepRotationZ = 0.0f; InitGeometry(); } CMeshView::~CMeshView() { } //******************************************** // InitGeometry //******************************************** void CMeshView::InitGeometry(void) { m_xRotation = 0.0f; m_yRotation = 0.0f; m_zRotation = 0.0f; m_xTranslation = 0.0f; m_yTranslation = 0.0f; m_zTranslation = -5.0f; m_xScaling = 1.0f; m_yScaling = 1.0f; m_zScaling = 1.0f; m_SpeedRotation = 1.0f / 3.0f; m_SpeedTranslation = 1.0f / 50.0f; m_xyRotation = 1; } BOOL CMeshView::PreCreateWindow(CREATESTRUCT& cs) { return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CMeshView drawing void CMeshView::OnDraw(CDC* pDC) { } ///////////////////////////////////////////////////////////////////////////// // CMeshView printing BOOL CMeshView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CMeshView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { } void CMeshView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { } ///////////////////////////////////////////////////////////////////////////// // CMeshView diagnostics #ifdef _DEBUG void CMeshView::AssertValid() const { CView::AssertValid(); } void CMeshView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMeshDoc* CMeshView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMeshDoc))); return (CMeshDoc*)m_pDocument; } #endif //_DEBUG ////////////////////////////////////////////// ////////////////////////////////////////////// // OPENGL ////////////////////////////////////////////// ////////////////////////////////////////////// //******************************************** // OnCreate // Create OpenGL rendering context //******************************************** int CMeshView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CView::OnCreate(lpCreateStruct) == -1) return -1; HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); if(SetWindowPixelFormat(hDC)==FALSE) return 0; if(CreateViewGLContext(hDC)==FALSE) return 0; // Default mode glPolygonMode(GL_FRONT,GL_FILL); glPolygonMode(GL_BACK,GL_FILL); glShadeModel(GL_FLAT); glEnable(GL_NORMALIZE); // Lights properties float ambientProperties[] = {0.7f, 0.7f, 0.7f, 1.0f}; float diffuseProperties[] = {0.8f, 0.8f, 0.8f, 1.0f}; float specularProperties[] = {1.0f, 1.0f, 1.0f, 1.0f}; glLightfv( GL_LIGHT0, GL_AMBIENT, ambientProperties); glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuseProperties); glLightfv( GL_LIGHT0, GL_SPECULAR, specularProperties); glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0); glClearColor(m_ClearColorRed,m_ClearColorGreen,m_ClearColorBlue,1.0f); glClearDepth(1.0f); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); // Perspective CRect rect; GetClientRect(&rect); double aspect = (rect.Height() == 0) ? rect.Width() : (double)rect.Width()/(double)rect.Height(); gluPerspective(45,aspect,0.1,1000.0); // Default : lighting glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); // Default : blending glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); // Default : material float MatAmbient[] = {0.0f, 0.5f, 0.75f, 1.0f}; float MatDiffuse[] = {0.0f, 0.5f, 1.0f, 1.0f}; float MatSpecular[] = {0.75f, 0.75f, 0.75f, 1.0f}; float MatShininess[] = { 64 }; float MatEmission[] = {0.0f, 0.0f, 0.0f, 1.0f}; float MatAmbientBack[] = {0.0f, 0.5f, 0.0f, 1.0f}; // green material behind glMaterialfv(GL_FRONT,GL_AMBIENT,MatAmbient); glMaterialfv(GL_FRONT,GL_DIFFUSE,MatDiffuse); glMaterialfv(GL_FRONT,GL_SPECULAR,MatSpecular); glMaterialfv(GL_FRONT,GL_SHININESS,MatShininess); glMaterialfv(GL_FRONT,GL_EMISSION,MatEmission); glMaterialfv(GL_BACK,GL_AMBIENT,MatAmbientBack); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); return 1; } ///////////////////////////////////////////////////////////////////////////// // CMeshView message handlers //********************************* // OnPaint //********************************* void CMeshView::OnPaint() { // Device context for painting CPaintDC dc(this); // Model is stored in Document CMeshDoc *pDoc = (CMeshDoc *)GetDocument(); //ASSERT_VALID(pDoc); // Useful in multidoc templates HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); wglMakeCurrent(hDC,m_hGLContext); glClearColor(m_ClearColorRed,m_ClearColorGreen,m_ClearColorBlue,1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); // Position / translation / scale glTranslated(m_xTranslation,m_yTranslation,m_zTranslation); glRotatef(m_xRotation, 1.0, 0.0, 0.0); glRotatef(m_yRotation, 0.0, 1.0, 0.0); glRotatef(m_zRotation, 0.0, 0.0, 1.0); glScalef(m_xScaling,m_yScaling,m_zScaling); // Start rendering... pDoc->RenderScene(); glPopMatrix(); // Double buffer SwapBuffers(dc.m_ps.hdc); glFlush(); // Release ::ReleaseDC(hWnd,hDC); } //******************************************** // SetWindowPixelFormat //******************************************** BOOL CMeshView::SetWindowPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pixelDesc; pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); pixelDesc.nVersion = 1; pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE; pixelDesc.iPixelType = PFD_TYPE_RGBA; pixelDesc.cColorBits = 32; pixelDesc.cRedBits = 8; pixelDesc.cRedShift = 16; pixelDesc.cGreenBits = 8; pixelDesc.cGreenShift = 8; pixelDesc.cBlueBits = 8; pixelDesc.cBlueShift = 0; pixelDesc.cAlphaBits = 0; pixelDesc.cAlphaShift = 0; pixelDesc.cAccumBits = 64; pixelDesc.cAccumRedBits = 16; pixelDesc.cAccumGreenBits = 16; pixelDesc.cAccumBlueBits = 16; pixelDesc.cAccumAlphaBits = 0; pixelDesc.cDepthBits = 32; pixelDesc.cStencilBits = 8; pixelDesc.cAuxBuffers = 0; pixelDesc.iLayerType = PFD_MAIN_PLANE; pixelDesc.bReserved = 0; pixelDesc.dwLayerMask = 0; pixelDesc.dwVisibleMask = 0; pixelDesc.dwDamageMask = 0; m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc); if(m_GLPixelIndex == 0) // Choose default { m_GLPixelIndex = 1; if(DescribePixelFormat(hDC,m_GLPixelIndex, sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0) return FALSE; } if(!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc)) return FALSE; return TRUE; } //******************************************** // CreateViewGLContext // Create an OpenGL rendering context //******************************************** BOOL CMeshView::CreateViewGLContext(HDC hDC) { m_hGLContext = wglCreateContext(hDC); if(m_hGLContext==NULL) return FALSE; if(wglMakeCurrent(hDC,m_hGLContext)==FALSE) return FALSE; return TRUE; } //********************************* // OnDestroy //********************************* void CMeshView::OnDestroy() { if(wglGetCurrentContext() != NULL) wglMakeCurrent(NULL,NULL); if(m_hGLContext != NULL) { wglDeleteContext(m_hGLContext); m_hGLContext = NULL; } CView::OnDestroy(); } //********************************* // OnSize //********************************* void CMeshView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); wglMakeCurrent(hDC,m_hGLContext); // Set OpenGL perspective, viewport and mode double aspect = (cy == 0) ? cx : (double)cx/(double)cy; glViewport(0,0,cx,cy); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45,aspect,0.1,1000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDrawBuffer(GL_BACK); // Release ::ReleaseDC(hWnd,hDC); } void CMeshView::OnLButtonDown(UINT nFlags, CPoint point) { m_LeftButtonDown = TRUE; m_LeftDownPos = point; SetCapture(); CView::OnLButtonDown(nFlags, point); } void CMeshView::OnLButtonUp(UINT nFlags, CPoint point) { m_RightButtonDown = FALSE; m_LeftButtonDown = FALSE; ReleaseCapture(); CView::OnLButtonUp(nFlags, point); } void CMeshView::OnRButtonDown(UINT nFlags, CPoint point) { m_RightButtonDown = TRUE; m_RightDownPos = point; SetCapture(); CView::OnRButtonDown(nFlags, point); } void CMeshView::OnRButtonUp(UINT nFlags, CPoint point) { m_RightButtonDown = FALSE; m_LeftButtonDown = FALSE; ReleaseCapture(); CView::OnRButtonUp(nFlags, point); } void CMeshView::OnMouseMove(UINT nFlags, CPoint point) { // Both : rotation if(m_LeftButtonDown && m_RightButtonDown) { if(m_xyRotation) { m_yRotation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedRotation; m_xRotation -= (float)(m_LeftDownPos.y - point.y) * m_SpeedRotation; } else { m_zRotation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedRotation; m_xRotation -= (float)(m_LeftDownPos.y - point.y) * m_SpeedRotation; } m_LeftDownPos = point; m_RightDownPos = point; InvalidateRect(NULL,FALSE); } else // Left : x / y translation if(m_LeftButtonDown) { m_xTranslation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedTranslation; m_yTranslation += (float)(m_LeftDownPos.y - point.y) * m_SpeedTranslation; m_LeftDownPos = point; InvalidateRect(NULL,FALSE); } else // Right : z translation if(m_RightButtonDown) { m_zTranslation += (float)(m_RightDownPos.y - point.y) * m_SpeedTranslation; m_RightDownPos = point; InvalidateRect(NULL,FALSE); } /* TRACE("\nPosition\n"); TRACE("Translation : %g %g %g\n",m_xTranslation,m_yTranslation,m_zTranslation); TRACE("Rotation : %g %g %g\n",m_xRotation,m_yRotation,m_zRotation); */ CView::OnMouseMove(nFlags, point); } BOOL CMeshView::OnEraseBkgnd(CDC* pDC) { return TRUE; return CView::OnEraseBkgnd(pDC); } void CMeshView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); wglMakeCurrent(hDC,m_hGLContext); ::ReleaseDC(hWnd,hDC); CView::OnActivateView(bActivate, pActivateView, pDeactiveView); } //********************************* // OnEditCopy //********************************* void CMeshView::OnEditCopy() { // Clean clipboard of contents, and copy the DIB. if(OpenClipboard()) { BeginWaitCursor(); // Snap CSize size; unsigned char *pixel = SnapClient(&size); // Image CTexture image; // Link image - buffer VERIFY(image.ReadBuffer(pixel,size.cx,size.cy,24)); // Cleanup memory delete [] pixel; EmptyClipboard(); SetClipboardData(CF_DIB,image.ExportHandle()); CloseClipboard(); EndWaitCursor(); } } // Hand-made client snapping unsigned char *CMeshView::SnapClient(CSize *pSize) { BeginWaitCursor(); // Client zone CRect rect; GetClientRect(&rect); //CSize size(CTexture::LowerPowerOfTwo(rect.Width()),rect.Height()); CSize size(rect.Width(),rect.Height()); *pSize = size; ASSERT(size.cx > 0); ASSERT(size.cy > 0); // Alloc unsigned char *pixel = new unsigned char[3*size.cx*size.cy]; ASSERT(pixel != NULL); // Capture frame buffer TRACE("Start reading client...\n"); TRACE("Client : (%d,%d)\n",size.cx,size.cy); CRect ClientRect,MainRect; this->GetWindowRect(&ClientRect); CWnd *pMain = AfxGetApp()->m_pMainWnd; CWindowDC dc(pMain); pMain->GetWindowRect(&MainRect); int xOffset = ClientRect.left - MainRect.left; int yOffset = ClientRect.top - MainRect.top; for(int j=0;j<size.cy;j++) for(int i=0;i<size.cx;i++) { COLORREF color = dc.GetPixel(i+xOffset,j+yOffset); pixel[3*(size.cx*(size.cy-1-j)+i)] = (BYTE)GetBValue(color); pixel[3*(size.cx*(size.cy-1-j)+i)+1] = (BYTE)GetGValue(color); pixel[3*(size.cx*(size.cy-1-j)+i)+2] = (BYTE)GetRValue(color); } EndWaitCursor(); return pixel; } //********************************* // OnExportEps //********************************* void CMeshView::OnExportEps() { static char BASED_CODE filter[] = "EPS Files (*.eps)|*.eps"; CFileDialog SaveDlg(FALSE,"*.eps","mesh.eps",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,filter); if(SaveDlg.DoModal() == IDOK) { CString string = SaveDlg.GetPathName(); char *pFilename = string.GetBuffer(MAX_PATH); // Alloc const int size = (int)6e6; // dirty code GLfloat *pFeedbackBuffer = new GLfloat[size]; ASSERT(pFeedbackBuffer); CDC *pDC = GetDC(); // Useful in multidoc templates ::wglMakeCurrent(pDC->m_hDC,m_hGLContext); // Set feedback mode ::glFeedbackBuffer(size,GL_3D_COLOR,pFeedbackBuffer); ::glRenderMode(GL_FEEDBACK); // Render ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Position / translation / scale ::glPushMatrix(); ::glTranslated(m_xTranslation,m_yTranslation,m_zTranslation); ::glRotatef(m_xRotation, 1.0, 0.0, 0.0); ::glRotatef(m_yRotation, 0.0, 1.0, 0.0); ::glRotatef(m_zRotation, 0.0, 0.0, 1.0); ::glScalef(m_xScaling,m_yScaling,m_zScaling); // Start rendering CMeshDoc *pDoc = GetDocument(); // Std rendering (no superimposed lines anyway) pDoc->m_SceneGraph.glDrawDirect(); ::glPopMatrix(); // Double buffer SwapBuffers(pDC->m_hDC); int NbValues = glRenderMode(GL_RENDER); // The stuff here CPsRenderer PsRenderer; PsRenderer.Run(pFilename,pFeedbackBuffer,NbValues,TRUE); // Cleanup string.ReleaseBuffer(); delete [] pFeedbackBuffer; ReleaseDC(pDC); } } void CMeshView::OnUpdateExportEps(CCmdUI* pCmdUI) { pCmdUI->Enable(GetDocument()->m_SceneGraph.NbObject() > 0); } //********************************* // OnOpenglClearcolor //********************************* void CMeshView::OnOpenglClearcolor() { COLORREF color = RGB((unsigned char)(m_ClearColorRed*255.0f), (unsigned char)(m_ClearColorGreen*255.0f), (unsigned char)(m_ClearColorBlue*255.0f)); CColorDialog dlg(color); if(dlg.DoModal() == IDOK) { color = dlg.GetColor(); m_ClearColorRed = (float)GetRValue(color)/255.0f; m_ClearColorGreen = (float)GetGValue(color)/255.0f; m_ClearColorBlue = (float)GetBValue(color)/255.0f; InvalidateRect(NULL,FALSE); } }